import re, os, sys
from elements import Elements

mass_electron = 0.000549

dir = os.path.dirname(os.path.abspath(__file__)) + os.sep + 'isotopes'
if sys.platform.startswith('win'):
    subdir = 'windows'
elif sys.platform.startswith('linux'):
    subdir = 'linux'

isotope_cmd = '%s%s%s%sisotopes' %(dir, os.sep, subdir, os.sep)
isotopes_dir = '%s%s%s' %(dir, os.sep, subdir)

reg_atoms = re.compile(r'([A-Z][a-z]*)')
reg_node = re.compile(r'([A-Z][a-z]*[0-9]*)')
reg_nms = re.compile(r'([0-9]+)')

repl_atoms = lambda x: '+%s' %x.groups()[0]
repl_nms = lambda x: '*%s' %x.groups()[0]

max_iso_dict = {}
min_iso_dict = {}
mw_dict = {}
for k, v in Elements.items():
    max_iso_dict[k] = v.ma
    min_iso_dict[k] = v.mi
    mw_dict[k] = v.mw

def fm2eq(fm):
    return reg_nms.sub(repl_nms, reg_atoms.sub(repl_atoms, fm)).replace('(+', '(')

def fm_parser(fm):
    result = []
    elist = reg_node.findall(fm)
    for e in elist:
        if reg_nms.findall(e) != []:
            result.append((reg_atoms.findall(e)[0], int(reg_nms.findall(e)[0])))
        else:
            result.append((e, 1))
    return result

def exact_mass(fm, chg = 0):
    d = {'emass': 0}
    d.update(max_iso_dict)
    cp = compile('emass=%s' %fm2eq(fm), '<string>', 'exec')
    eval(cp, d)
    #print fm2eq(fm)
    return d['emass'] - chg * mass_electron

def min_mass(fm):
    d = {'minmass': 0}
    d.update(min_iso_dict)
    cp = compile('minmass=%s' %fm2eq(fm), '<string>', 'exec')
    eval(cp, d)
    #print fm2eq(fm)
    return d['minmass']

def iso_distr(fm):
    pwd0 = os.pardir
    os.chdir(isotopes_dir)
    result = []
    for line in os.popen('%s %s' %(isotope_cmd, fm)).readlines():
        result.append([float(i) for i in line.strip(' \r\n').split() if i != ''])
    os.chdir(pwd0)
    return result

def mol_weight(fm):
    d = {'mw': 0}
    d.update(mw_dict)
    cp = compile('mw=%s' %fm2eq(fm), '<string>', 'exec')
    eval(cp, d)
    #print fm2eq(fm)
    return d['mw']

if __name__ == '__main__':
    ks = Elements.keys()
    ks.sort()
    #for k in ks:
        #print k, Elements[k].ano
    fm = 'CH3O4BrI'
    print fm_parser(fm)
    print iso_distr(fm)
    print exact_mass(fm)
    print mol_weight(fm)

